home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / daytime.zip / daytime.c next >
C/C++ Source or Header  |  1997-04-24  |  7KB  |  285 lines

  1. /* daytime.c - set local time from remote daytime or time server
  2.  *
  3.  * for IBM TCP/IP 2.0 for OS/2
  4.  *
  5.  * Author:  Kai Uwe Rommel <rommel@ars.muc.de>
  6.  * Created: Sun Apr 10 1994
  7.  *
  8.  * This code is in the public domain. 
  9.  * Let the author know if you make improvements or fixes, though.
  10.  */
  11.  
  12. static char *rcsid =
  13. "$Id: daytime.c,v 1.8 1996/12/08 11:18:04 rommel Exp rommel $";
  14. static char *rcsrev = "$Revision: 1.8 $";
  15.  
  16. /*
  17.  * $Log: daytime.c,v $
  18.  * Revision 1.8  1996/12/08 11:18:04  rommel
  19.  * added get_date prototype
  20.  *
  21.  * Revision 1.7  1996/12/08 11:15:07  rommel
  22.  * don't change time within 1 second margin
  23.  * from Ewen McNeill <ewen@naos.co.nz>
  24.  *
  25.  * Revision 1.6  1996/11/29 15:45:00  rommel
  26.  * changes (maxadj) from Ewen McNeill <ewen@naos.co.nz>
  27.  *
  28.  * Revision 1.5  1995/08/20 08:15:10  rommel
  29.  * updated for new emx socket library, IBM compiler
  30.  * fixed minor bugs
  31.  *
  32.  * Revision 1.4  1994/07/17 21:13:26  rommel
  33.  * fixed usage() display again
  34.  *
  35.  * Revision 1.3  1994/07/17 21:10:23  rommel
  36.  * fixed usage() display
  37.  *
  38.  * Revision 1.2  1994/07/17 21:07:57  rommel
  39.  * added daemon mode, continuously updating local time
  40.  *
  41.  * Revision 1.1  1994/07/17 20:45:55  rommel
  42.  * Initial revision
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <getopt.h>
  48. #include <time.h>
  49. #include <string.h>
  50.  
  51. #ifdef OS2
  52. #ifdef __IBMC__
  53. #define BSD_SELECT
  54. #include <types.h>
  55. #include <sys/select.h>
  56. #endif
  57. #include <sys/types.h>
  58. #include <sys/time.h>
  59. #include <sys/socket.h>
  60. #include <netinet/in.h>
  61. #include <netdb.h>
  62. #ifdef __EMX__
  63. #define psock_errno perror
  64. #define soclose close
  65. #define sock_init() 0
  66. #endif
  67. #endif
  68.  
  69. typedef enum {TIME = 0, DAYTIME = 1} service;
  70. typedef enum {UDP = 0, TCP = 1} protocol;
  71.  
  72. time_t get_date(char *p, void *now);
  73.  
  74. #ifdef OS2
  75.  
  76. #define INCL_DOS
  77. #include <os2.h>
  78.  
  79. int stime(time_t *newtime)
  80. {
  81.   struct tm *newtm = localtime(newtime);
  82.   DATETIME dt;
  83.  
  84.   dt.hours   = newtm -> tm_hour;
  85.   dt.minutes = newtm -> tm_min;
  86.   dt.seconds = newtm -> tm_sec;
  87.   dt.hundredths = 0;
  88.  
  89.   dt.day     = newtm -> tm_mday;
  90.   dt.month   = newtm -> tm_mon + 1;
  91.   dt.year    = newtm -> tm_year + 1900;
  92.   dt.weekday = newtm -> tm_wday;
  93.  
  94.   dt.timezone = -1;
  95.  
  96.   return DosSetDateTime(&dt) != 0;
  97. }
  98.  
  99. #endif
  100.  
  101. int get_and_set_time(int dont, int port, char *node, 
  102.              service serv, protocol proto, time_t offs, time_t maxadj)
  103. {
  104.   int sock, bytes, size;
  105.   struct sockaddr_in server;
  106.   struct hostent *host;
  107.   struct linger linger;
  108.   time_t now;
  109.   time_t here;
  110.   char buffer[64];
  111.  
  112.   if ((host = gethostbyname(node)) == NULL)
  113.     return psock_errno("gethostbyname()"), 1;
  114.  
  115.   server.sin_family = AF_INET;
  116.   server.sin_port = port;
  117.   server.sin_addr = * (struct in_addr *) (host -> h_addr);
  118.  
  119.   if (proto == TCP)
  120.   {
  121.     if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  122.       return psock_errno("socket(tcp)"), 1;
  123.  
  124.     if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
  125.       return psock_errno("connect()"), 1;
  126.  
  127.     if ((bytes = recv(sock, buffer, sizeof(buffer), 0)) <= 0)
  128.       return psock_errno("recv()"), 1;
  129.   }
  130.   else
  131.   {
  132.     if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
  133.       return psock_errno("socket(udp)"), 1;
  134.  
  135.     if (sendto(sock, "", 1, 0,
  136.                (struct sockaddr *) &server, sizeof(server)) < 0)
  137.       return psock_errno("sendto()"), 1;
  138.  
  139.     size = sizeof(server);
  140.     if ((bytes = recvfrom(sock, buffer, sizeof(buffer), 0,
  141.                           (struct sockaddr *) &server, &size)) < 0)
  142.       psock_errno("recvfrom()");
  143.   }
  144.  
  145.   soclose(sock);
  146.  
  147.   if (serv == DAYTIME)
  148.   {
  149.     buffer[bytes] = 0;
  150.     now = get_date(buffer, NULL);
  151.   }
  152.   else
  153.   {
  154.     if (bytes != sizeof(now))
  155.       return printf("invalid time value received\n"), 1;
  156.     else
  157.     {
  158.       now = * (time_t *) buffer;
  159.       now = ntohl(now);
  160.  
  161.       /*
  162.        * The time service returns seconds since 1900/01/01 00:00:00 GMT, not
  163.        * since 1970 as assumed by Unix time_t values.  We need to subtract
  164.        * 70 years' worth of seconds.  Fortunately, RFC 868 tells us that the 
  165.        * daytime value 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT.
  166.        */
  167.       now -= 2208988800UL;
  168.     }
  169.   }
  170.  
  171.   if (now <= 0)
  172.     return printf("invalid time\n"), 1;
  173.  
  174.   now += offs;
  175.   time(&here);
  176.  
  177.   if (maxadj)
  178.     if (now < (here - maxadj) || (here + maxadj) < now)
  179.       dont = 1;               /* Too far off: just report it */
  180.  
  181.   if (abs(now - here) <= 1)
  182.     dont = 1;
  183.   
  184.   if (!dont && stime(&now))
  185.     return printf("invalid time set request\n"), 1;
  186.  
  187.   printf("time %s %s: (%+ld) %s", dont ? "at" : "set from", 
  188.      host -> h_name, now - here, ctime(&now));
  189.   fflush(stdout);
  190.  
  191.   return 0;
  192. }
  193.  
  194. int usage(void)
  195. {
  196.   printf("\nUsage: daytime [-ndtTU] [-m secs] [-c int] [-p port] host\n"
  197.          "\n  -n       do not set the local clock, display the remote time only"
  198.      "\n  -c int   run continuously, perform action every 'int' seconds"
  199.          "\n  -o offs  adjust the retrieved time by offs seconds before"
  200.      "\n           setting the local clock"
  201.      "\n  -m secs  Maximum number of seconds to adjust by\n"
  202.          "\n  -d       use the 'daytime' service (port 13)"
  203.          "\n  -t       use the 'time' service (port 37, default)"
  204.      "\n  -T       use the 'tcp' protocol (default)"
  205.      "\n  -U       use the 'udp' protocol"
  206.      "\n  -p port  use nonstandard port number\n");
  207.   return 1;
  208. }
  209.  
  210. int main(int argc, char **argv)
  211. {
  212.   int opt, portnum = -1, daytime = 0, dont = 0;
  213.   char *host = NULL;
  214.   struct servent *port;
  215.   service serv = TIME;
  216.   protocol proto = TCP;
  217.   time_t offset = 0;
  218.   int interval = 0;
  219.   int maxadj = 0;                 /* Maximum number of seconds to adjust by
  220.                                    * where 0 = no maximum.  EDM, 27/11/96 */
  221.   tzset();
  222.  
  223.   if (sock_init())
  224.     return psock_errno("sock_init()"), 1;
  225.  
  226.   while ((opt = getopt(argc, argv, "?ndtTUo:p:c:m:")) != EOF)
  227.     switch (opt)
  228.     {
  229.     case 'n':
  230.       dont = 1;
  231.       break;
  232.     case 'd':
  233.       serv = DAYTIME;
  234.       break;
  235.     case 't':
  236.       serv = TIME;
  237.       break;
  238.     case 'T':
  239.       proto = TCP;
  240.       break;
  241.     case 'U':
  242.       proto = UDP;
  243.       break;
  244.     case 'o':
  245.       offset = atol(optarg);
  246.       break;
  247.     case 'p':
  248.       portnum = htons(atoi(optarg));
  249.       break;
  250.     case 'c':
  251.       interval = atol(optarg);
  252.       break;
  253.     case 'm':
  254.       maxadj = atol(optarg);
  255.       break;
  256.     default:
  257.       return usage();
  258.     }
  259.  
  260.   if (optind == argc)
  261.     return usage();
  262.   else
  263.     host = argv[optind];
  264.  
  265.   if (portnum == -1)
  266.   {
  267.     if ((port = getservbyname(serv == DAYTIME ? "daytime" : "time", 
  268.                   proto == TCP ? "tcp" : "udp")) == NULL)
  269.       return psock_errno("getservbyname()"), 1;
  270.  
  271.     portnum = port -> s_port;
  272.   }
  273.  
  274.   if (interval == 0)
  275.     return get_and_set_time(dont, portnum, host, serv, proto, offset, maxadj);
  276.  
  277.   for (;;)
  278.   {
  279.     get_and_set_time(dont, portnum, host, serv, proto, offset, maxadj);
  280.     sleep(interval);
  281.   }
  282. }
  283.  
  284. /* end of daytime.c */
  285.